package com.future;

/**
 * Description:
 * 有 n 个城市，其中一些彼此相连，另一些没有相连。如果城市 a 与城市 b 直接相连，且城市 b 与城市 c 直接相连，那么城市 a 与城市 c 间接相连。
 * 省份 是一组直接或间接相连的城市，组内不含其他没有相连的城市。
 * 给你一个 n x n 的矩阵 isConnected ，其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连，而 isConnected[i][j] = 0 表示二者不直接相连。
 * 返回矩阵中 省份 的数量
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/number-of-provinces
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 * @author weiruibai.vendor
 * Date: 2021/12/13 09:28
 */
public class Solution_findCircleNum_547 {


    public static void main(String[] args) {
        int[][] M = {
                {1, 1, 0, 0, 1},
                {1, 1, 0, 0, 1},
                {0, 0, 1, 1, 1},
                {0, 0, 0, 1, 1},
                {0, 0, 0, 1, 1}
        };
        int circleNum = findCircleNum(M);
        System.out.println(circleNum);

    }

    public static int findCircleNum(int[][] isConnected) {
        UnionFind unionFind = new UnionFind(isConnected.length);
        for (int i = 0; i < isConnected.length - 1; i++) {
            for (int j = i + 1; j < isConnected.length; j++) {
                if (isConnected[i][j] == 1) {
                    unionFind.union(i, j);
                }
            }
        }
        return unionFind.getSize();
    }

    private static class UnionFind {

        // index-value
        int[] value;

        // child-father
        int[] parent;

        // 下标为index的有多少个
        int[] size;

        int ans;

        public UnionFind(int N) {
            value = new int[N];
            parent = new int[N];
            size = new int[N];
            ans = N;
            for (int i = 0; i < N; i++) {
                parent[i] = i;
                size[i] = 1;
            }
        }

        public void union(int i, int j) {
            int iFather = findFather(i);
            int jFather = findFather(j);
            if (iFather != jFather) {
                int iCount = size[iFather];
                int jCount = size[jFather];
                if (iCount >= jCount) {
                    parent[jFather] = iFather;
                    size[i] = iCount + jCount;
                    size[j] = 0;
                } else {
                    parent[iFather] = jFather;
                    size[j] = iCount + jCount;
                    size[i] = 0;
                }
                /**
                 * 每一次合并，集合个数会少一个
                 */
                ans--;
            }
        }

        public int findFather(int val) {
            int father = parent[val];
            while (val != parent[val]) {
                val = parent[val];
            }
            return val;
        }

        public int getSize() {
            return ans;
        }
    }
}
